package com.springboot.frame.starter.utils;

import com.fasterxml.jackson.core.JsonGenerator;
import com.fasterxml.jackson.core.type.TypeReference;
import com.fasterxml.jackson.databind.JsonSerializer;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.databind.SerializerProvider;
import com.fasterxml.jackson.datatype.jsr310.JavaTimeModule;
import lombok.extern.slf4j.Slf4j;

import java.io.IOException;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;

/**
 * Json转换工具类
 *
 * @author madman
 */
@Slf4j
public final class JsonUtils {
    public static final String dateFormat = "yyyy-MM-dd";
    public static final String dateTimeFormat = "yyyy-MM-dd HH:mm:ss";
    private static final ObjectMapper OBJECTMAPPER = new ObjectMapper();

    private JsonUtils() {
    }

    /**
     * 转换LocalDateTime
     */
    static class LocalDateTimeSerializer extends JsonSerializer<LocalDateTime> {
        @Override
        public void serialize(LocalDateTime localDateTime, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(localDateTime.format(DateTimeFormatter.ofPattern(dateTimeFormat)));
        }
    }

    /**
     * 转换LocalDate
     */
    static class LocalDateSerializer extends JsonSerializer<LocalDate> {
        @Override
        public void serialize(LocalDate localDate, JsonGenerator jsonGenerator, SerializerProvider serializerProvider) throws IOException {
            jsonGenerator.writeString(localDate.format(DateTimeFormatter.ofPattern(dateFormat)));
        }
    }

    /**
     * 将对象序列化
     */
    public static <T> String toJsonString(T obj) throws IOException {
        JavaTimeModule timeModule = new JavaTimeModule();
        timeModule.addSerializer(LocalDateTime.class, new LocalDateTimeSerializer());
        timeModule.addSerializer(LocalDate.class, new LocalDateSerializer());
        OBJECTMAPPER.registerModule(timeModule);
        return OBJECTMAPPER.writeValueAsString(obj);
    }

    /**
     * 反序列化对象字符串
     */
    public static <T> T parseObject(String json, Class<T> clazz) throws IOException {
        return OBJECTMAPPER.readValue(json, clazz);
    }

    /**
     * 反序列化字符串成为对象
     */
    public static <T> T parseObject(String json, TypeReference<T> valueTypeRef) throws IOException {
        return OBJECTMAPPER.readValue(json, valueTypeRef);
    }

}
